package otcv.hr.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import otcv.hr.log.Logger;

/**
 * @author : H-Thien
 * @comment :
 */
public class FileHelper {

	/**
	 * @comment :
	 */
	private FileHelper() {

	}

	/**
	 * @comment :
	 */
	private static void writeAscii(String path, String content) throws IOException {
		OutputStreamWriter fs = new OutputStreamWriter(new FileOutputStream(path));
		PrintWriter writer = new PrintWriter(fs);
		writer.println(content);
		writer.close();
		fs.close();
	}

	/**
	 * @comment :
	 */
	public static void write(String path, String content) throws Exception {
		try {
			writeAscii(path, content);
		} catch (Exception e) {
			createDirectory(path);
			writeAscii(path, content);
		}
	}

	/**
	 * @comment :
	 */
	private static void writeBinary(String path, InputStream stream) throws Exception {
		OutputStream bos = new FileOutputStream(path);
		int bytesRead = 0;
		byte[] buffer = new byte[8192];

		while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
			bos.write(buffer, 0, bytesRead);
		}
		bos.close();
	}

	/**
	 * @comment :
	 */
	public static void write(String path, InputStream stream) throws Exception {
		try {
			writeBinary(path, stream);
		} catch (Exception e) {
			createDirectory(path);
			writeBinary(path, stream);
		}
	}

	/**
	 * @comment :
	 */
	private static void writeAscii(File path, String content) throws IOException {
		FileOutputStream fs = new FileOutputStream(path);
		PrintWriter writer = new PrintWriter(fs);
		writer.println(content);
		writer.close();
		fs.close();
	}

	/**
	 * @comment :
	 */
	public static void write(File file, String content) throws Exception {
		try {
			writeAscii(file, content);
		} catch (Exception e) {
			createDirectory(file.getAbsolutePath());
			writeAscii(file, content);
		}
	}

	/**
	 * @comment :
	 */
	private static void writeBinary(File path, InputStream stream) throws Exception {
		OutputStream bos = new FileOutputStream(path);
		int bytesRead = 0;
		byte[] buffer = new byte[8192];

		while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
			bos.write(buffer, 0, bytesRead);
		}
		bos.close();
	}

	/**
	 * @comment :
	 */
	public static void write(File file, InputStream stream) throws Exception {
		try {
			writeBinary(file, stream);
		} catch (Exception e) {
			createDirectory(file.getAbsolutePath());
			writeBinary(file, stream);
		}
	}

	/**
	 * @comment :
	 */
	public static String read(String path) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(path));
		return read(br).toString();
	}

	/**
	 * @comment :
	 */
	public static String read(File path) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(path));
		return read(br).toString();
	}

	/**
	 * @comment :
	 */
	private static StringBuffer read(BufferedReader reader) throws IOException {
		StringBuffer buff = new StringBuffer();
		boolean flag = true;
		while (true) {
			String temp = reader.readLine();
			if (temp == null) {
				break;
			} else if (flag) {
				flag = false;
				buff.append(temp);
			} else {
				buff.append("\n" + temp);
			}
		}

		return buff;
	}

	/**
	 * @comment :
	 */
	public static void createDirectory(String path) {
		StringBuffer buff = new StringBuffer(path);
		int old = 0;
		for (int i = 0; i < buff.length(); i++) {
			if (File.separator.equals(buff.charAt(i) + "")) {
				File _newFile = new File(buff.substring(old, i));
				if (!_newFile.isDirectory()) {
					_newFile.mkdirs();
				}
			}
		}
	}

	/**
	 * @comment :
	 */
	public static void createDirectory(String path, String dirName) throws Exception {
		if (path == null) {
			throw new Exception("Can Not Create Dir -> " + dirName + "[NeedPath]");
		} else {
			if (path.charAt(path.length() - 1) != File.separatorChar) {
				path = path + File.separator;
			}
		}

		createDirectory(path);

		File file = new File(path + dirName);
		if (file.exists() == false && file.mkdir() == false) {
			throw new Exception("Can Not Create Dir -> " + path + dirName);
		}
	}

	/**
	 * @comment :
	 */
	public static void renameTo(String oldPath, String newPath) throws Exception {
		File oldFile = new File(oldPath);
		File newFile = new File(newPath);

		if (oldFile.isFile()) {
			if (newFile.exists() == false) {
				if (oldFile.renameTo(newFile) == false) {
					throw new Exception("ReName Fail" + "[" + oldPath + "]" + "->" + "[" + newPath + "]");
				}
			} else {
				FileInputStream in = null;
				FileOutputStream out = null;

				try {
					in = new FileInputStream(oldFile);
					out = new FileOutputStream(newFile);
					synchronized (in) {
						synchronized (out) {
							byte[] buffer = new byte[4096];
							while (true) {
								int byteRead = in.read(buffer);
								if (byteRead == -1) {
									break;
								}
								out.write(buffer, 0, byteRead);
							}
						}
					}

					if (oldFile.delete() == false) {
						Logger.debug(oldPath + " Delete Failure");
					}
				} catch (Exception e) {

				} finally {
					if (in != null)
						in.close();
					if (out != null)
						out.close();
				}
			}
		} else {
			throw new Exception("OldFile No Exist" + oldPath);
		}
	}

	/**
	 * @comment :
	 */
	public static void copy(File f, String path) throws IOException {
		FileInputStream in = null;
		FileOutputStream out = null;

		try {
			in = new FileInputStream(f);
			out = new FileOutputStream(new File(path));
			synchronized (in) {
				synchronized (out) {
					byte[] buffer = new byte[4096];
					while (true) {
						int byteRead = in.read(buffer);
						if (byteRead == -1) {
							break;
						}
						out.write(buffer, 0, byteRead);
					}
				}
			}
		} catch (Exception e) {

		} finally {
			if (in != null)
				in.close();
			if (out != null)
				out.close();
		}
	}

	/**
	 * @comment :
	 */
	public static void rmMinusRf(String path) {
		File f = new File(path);
		if (f.exists() == false) {
			return;
		}

		if (f.isFile()) {
			f.delete();
			return;
		}

		String[] fileList = f.list();
		if (fileList == null)
			return;
		for (int i = 0; i < fileList.length; i++) {
			File tmp = new File(path + File.separator + fileList[i]);
			if (tmp.isDirectory()) {
				rmMinusRf(path + File.separator + fileList[i]);
				tmp.delete();
			} else {
				tmp.delete();
			}
		}
		f.delete();
	}

	/**
	 * @comment :
	 */
	public static long getTotalSize(String path) {
		File f = new File(path);
		long totalSize = 0;

		if (f.isFile()) {
			return f.length();
		}

		String[] fileList = f.list();
		if (fileList == null) {
			return totalSize;
		}

		for (int i = 0; i < fileList.length; i++) {
			File tmp = new File(path + File.separator + fileList[i]);
			if (tmp.isDirectory()) {
				totalSize += getTotalSize(path + File.separator + fileList[i]);
			} else {
				totalSize += tmp.length();
			}
		}
		return totalSize;
	}

	/**
	 * @comment :
	 */
	public static boolean copyDirectory(String sourceDirectoryAbsolutePath, String destDirectoryAbsolutePath) throws IOException {
		File sourceDir = new File(sourceDirectoryAbsolutePath);
		File destDir = new File(destDirectoryAbsolutePath);
		if (sourceDir.isDirectory()) {
			String[] sourceFileList = sourceDir.list();
			if (destDir.exists() != true) {
				destDir.mkdir();
			} else {
				Logger.debug("[copyDirectory] : Destination Directory Paht parameter is not Absolute Path or Not a Directory");
				return false;
			}

			if (sourceFileList != null) {
				for (int i = 0; i < sourceFileList.length; i++) {
					String sourceFileAbsolutePath = sourceDirectoryAbsolutePath + File.separator + sourceFileList[i];
					File sourceFile = new File(sourceFileAbsolutePath);
					String destFileAbsolutePath = destDirectoryAbsolutePath + File.separator + sourceFileList[i];

					try {
						copy(sourceFile, destFileAbsolutePath);
					} catch (IOException e) {
						Logger.debug(e);
						throw new IOException(e.getMessage());
					}
				}
				return true;
			} else {
				Logger.debug("[copyDirectory] : There is notthing in Destnation Directory ");
				return false;
			}
		} else {
			Logger.debug("[copyDirectory] : Source Directory Paht parameter is not Absolute Path or Not a Directory");
			return false;
		}
	}

	/**
	 * @comment :
	 */
	public static boolean exist(String path) {
		File f = new File(path);
		return f.exists();
	}
}
